package com.nonagon.melladesk.service;

import com.nonagon.melladesk.entity.RoleEntity;
import com.nonagon.melladesk.repository.*;
import com.nonagon.melladesk.utils.RRException;
import com.nonagon.melladesk.vo.UserDetail;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.HashSet;
import java.util.Set;


/**
 * @author flitsneak
 * @ClassName
 * @date 2021/3/22 16:09
 */
@RequiredArgsConstructor
@Service
public class UserDetailService implements ReactiveUserDetailsService {

    private final UserRepository userRepository;

    private final UserRoleRepository userRoleRepository;

    private final RoleRepository roleRepository;

    private final UserIdentityRepository userIdentityRepository;

    private final IdentityRepository identityRepository;

    @Override
    public Mono<UserDetails> findByUsername(String email) {

        //返回权限列表，并把权限放入List<RoleEntity>中。
        return userRepository.findAllByEmail(email)
                .switchIfEmpty(Mono.error(new RRException("查无此人")))
                .map(o->{
                    UserDetail userDetail = new UserDetail();
                    Set<RoleEntity> roles = new HashSet<>();
                    //查询密码
                    userIdentityRepository.findByIdentityTypeIdAndUserId(1, o.getUserId())
                            .subscribe(u -> {
                                identityRepository.findById(u.getIdentityId()).subscribe(p->{
                                   userDetail.setHash(p.getHash());
                                });
                            });
                    //查询权限列表
                    userRoleRepository.findAllByUserId(o.getUserId()).subscribe(p->{
                        roleRepository.findById(p.getRoleId()).subscribe(q->{
                            roles.add(q);
                        });
                    });
                    userDetail.setRoles(roles);

                    return Mono.just(userDetail);
                })
                .map(UserDetails.class::cast);//映射
    }
}
